﻿using System;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Collections.Concurrent;
using System.Xml;
using System.Xml.Serialization;
using System.Collections.Generic;
using DiPlaner.Profile;
using DiPlaner.Properties;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;
using Microsoft.Win32;
using System.Security.Permissions;
using System.Linq.Expressions;

[assembly: RegistryPermissionAttribute(
    action: SecurityAction.RequestMinimum,
    ViewAndModify = "HKEY_CURRENT_USER")]

namespace DiPlaner
{
    
    public partial class DiForm : Form
    {/*
        #region VARIABLES

        #region _private

        SynchronizationContext main_context = new SynchronizationContext();

        int idleCount, CheckCounter;
        bool firstStart = true;

        #endregion

        #region _public

        public static readonly WorkerClass Worker = new WorkerClass();
        public static List<ListTemplate> BotLines = new List<ListTemplate>();

        public static volatile bool CheckAllow = true;
        public static bool Hooked;

        public static Stopwatch sysWatch = new Stopwatch();

        public static string _lastdb_path;
        public static string _lastd3_path;

        #endregion

        #endregion


        #region DiForm
        //*/
        public DiForm()
        {
            InitializeComponent();
            /*
            FormClosed += ActiveForm_FormClosed;

            main_context = SynchronizationContext.Current ?? new SynchronizationContext();

            Settings.Default.Upgrade();
            if (Settings.Default.ProfileList != null)
                for (var i = 0; Settings.Default.ProfileList.Count > i && i <= 10; i++)
                {
                    if (File.Exists(Settings.Default.ProfileList[i]))
                        CB_Profile.Items.Add(Settings.Default.ProfileList[i]);
                }
            if (Settings.Default.LastProfile != null && CB_Profile.Items.Contains(Settings.Default.LastProfile)) LoadPlanFile(Settings.Default.LastProfile);
            _lastd3_path = !string.IsNullOrEmpty(Settings.Default.lastD3) ? Settings.Default.lastD3 : string.Empty;
            _lastdb_path = !string.IsNullOrEmpty(Settings.Default.lastDB) ? Settings.Default.lastDB : string.Empty;

            timer.Start();
        //*/
        }/*

        private void timer_Tick(object sender, EventArgs e) 
        {
            curloctime.Text = string.Format("Local Time {0}", DateTime.Now.ToString("HH:mm:ss"));

        }

        private void DiForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            timer.Stop();
            Worker.StopWork();
            Program.StopHook();
        }

        void ActiveForm_FormClosed(object sender, FormClosedEventArgs e)
        {
            Settings.Default.LastProfile = (string)CB_Profile.SelectedItem;
            if (CB_Profile.Items != null && CB_Profile.Items.Count > 0)
            {
                Settings.Default.ProfileList = new System.Collections.Specialized.StringCollection();
                foreach (string path in CB_Profile.Items) Settings.Default.ProfileList.Add(path);
            }
            Settings.Default.lastD3 = _lastd3_path;
            Settings.Default.lastDB = _lastdb_path;
            Settings.Default.Save();
        }

        #endregion

        
        #region UI LOG

        private void bt_openlog_Click(object sender, EventArgs e)
        {
            var proc = new Process {StartInfo = {FileName = tb_logfile.Text}};
            proc.Start();
            proc.Dispose();
        }

        private void bt_log_Click(object sender, EventArgs e)
        {
            if (Size.Width <= 301)
            {
                Size = new Size(655, Size.Height);
                MinimumSize = new Size(655, 182);
                MaximumSize = new Size(655, 560);

            } else
            {
                Size = new Size(300, Size.Height);
                MinimumSize = new Size(300, 182);
                MaximumSize = new Size(300, 560);
            }
        }
        #endregion


        #region UI EVENTS

        private void btn_addPlan_Click(object sender, EventArgs e) 
        {
            if (BotLines.Count >= 99) {
                MessageBox.Show("Maximum number of plans exeded!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            BotLines.Add(new ListTemplate());
            if (list_floPan.Size.Height < BotLines.Count * 48 && list_floPan.Size.Height < 385)
            {
                var _size = Size;
                Size = new Size(_size.Width, Math.Min(MaximumSize.Height, _size.Height + 48));
            }

            var a = 1;
            BotLines.ForEach(line =>
            {
                if (!line.init)
                    line.Initialize(a);
                if (a > list_floPan.Controls.Count)
                    list_floPan.Controls.Add(line);
                a++;
            });

            list_floPan.Refresh();
        }

        private void BT_ProfileBrowse_Click(object sender, EventArgs e)
        {
            openFile.Filter = "Profile|*.xml";
            openFile.Title = "Select profile";
            openFile.ShowDialog();
            var path = openFile.FileName;
            if (path.Length > 0)
            {
                LoadPlanFile(path);
            }
        }
        
        private void CB_Profile_SelectedIndexChanged(object sender, EventArgs e)
        {
            LoadPlanFile((string)((ComboBox)sender).SelectedItem);
        }

        private void CB_Profile_Format(object sender, ListControlConvertEventArgs e)
        {
            try
            {
                e.Value = Path.GetFileName(e.Value.ToString());
            }
            catch { }
        }
        
        private void trayIcon_DoubleClick(object sender, EventArgs e)
        {
            if (WindowState != FormWindowState.Minimized) return;
            Show();
            WindowState = FormWindowState.Normal;
            ShowInTaskbar = true;
            trayIcon.Visible = false;
        }

        private void DiForm_Resize(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Minimized)
            {
                Hide();
                ShowInTaskbar = false;
                trayIcon.Visible = true;
            }

            list_floPan.Size = new Size(280, Size.Height - 135);
            logbox.Size = new Size(350, Size.Height - 75);

        }

        #endregion

        
        #region PROFILE FUNCTIONS

        private void Scheduler(Profile.BotStatus status = Profile.BotStatus.idle)
        {
            if (!sysWatch.IsRunning) return;

            Text = "Di Planer v2" + string.Format(" [Runing {0:0}:{1:00}:{2:00}:{3:00}]", 
                sysWatch.Elapsed.Days, sysWatch.Elapsed.Hours, sysWatch.Elapsed.Minutes, sysWatch.Elapsed.Seconds);

            
        }

        public void LoadPlanFile(string path)
        {
            try
            {
                if (File.Exists(path))
                {
                    var key = new DESCryptoServiceProvider();
                    var d = key.CreateDecryptor(Encoding.ASCII.GetBytes("64bP"), Encoding.ASCII.GetBytes("z6b4p"));
                    using (var fs = File.Open(path, FileMode.Open))
                    using (var cs = new CryptoStream(fs, d, CryptoStreamMode.Read))
                        BotLines = (List<ListTemplate>)(new XmlSerializer(typeof (List<ListTemplate>))).Deserialize(cs);
                } else
                {
                    throw new FileNotFoundException("Plan file not found");
                }

                if (!CB_Profile.Items.Contains(path))
                    CB_Profile.Items.Add(path);
                CB_Profile.SelectedItem = path;
                CheckBotLines();
            }
            catch (Exception e) {
                MessageBox.Show("Incorrect Profile!\r\n" + e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                CB_Profile.Items.Remove(path);
            }
        }

        public void SavePlanFile(bool button = false)
        {
            var filePath = string.Empty;

            if (button || string.IsNullOrEmpty(CB_Profile.SelectedItem.ToString()))
            {
                saveFile.DefaultExt = ".xml";
                if (!string.IsNullOrEmpty(Settings.Default.LastProfile)) saveFile.InitialDirectory =
                    Settings.Default.LastProfile.Substring(0, Settings.Default.LastProfile.LastIndexOf('\\') - 1);
                saveFile.ShowDialog();

                if (!string.IsNullOrEmpty(saveFile.FileName))
                {
                    if (!CB_Profile.Items.Contains(saveFile.FileName)) CB_Profile.Items.Add(saveFile.FileName);

                    filePath = saveFile.FileName;
                    Settings.Default.LastProfile = saveFile.FileName;
                    Settings.Default.ProfileList = new System.Collections.Specialized.StringCollection();

                    if (CB_Profile.Items != null) foreach (string path in CB_Profile.Items) Settings.Default.ProfileList.Add(path);
                }
            }

            if (filePath == null)
                filePath = System.Reflection.Assembly.GetExecutingAssembly().Location + "_tempProfile.xml";

            var key = new DESCryptoServiceProvider();
            var e = key.CreateEncryptor(Encoding.ASCII.GetBytes("64bP"), Encoding.ASCII.GetBytes("z6b4p"));
            using (var fs = File.Open(filePath, FileMode.Create))
            using (var cs = new CryptoStream(fs, e, CryptoStreamMode.Write))
                (new XmlSerializer(typeof(List<ListTemplate>))).Serialize(cs, BotLines);

            CB_Profile.SelectedItem = filePath;
        }

        #endregion

        
        #region UI START/STOP/SAVE

        private void bt_startAll_Click(object sender, EventArgs e)
        {
            firstStart = true;

            Settings.Default.StartDate = DateTime.Now;

            SavePlanFile();
            
            bt_startAll.Visible = false;
            bt_stopAll.Visible = true;
            bt_save.Visible = false;

            CB_Profile.Enabled = false;
            BT_ProfileBrowse.Enabled = false;
            
            Worker.RunWorker(logbox, Log);

            idleCount = 0;

            Program.StartHook();
        }

        private void bt_stopAll_Click(object sender, EventArgs e)
        {
            DiRunTime.StopAllSlots();

            bt_startAll.Visible = true;
            bt_stopAll.Visible = false;
            bt_save.Visible = true;
            
            CB_Profile.Enabled = true;
            BT_ProfileBrowse.Enabled = true;
            
            Program.StopHook();
        }


        private void bt_save_Click(object sender, EventArgs e)
        {
            SavePlanFile(true);
        }
        
        #endregion


        #region UI SLOTS

        void CheckBotLines()
        {
            var readyCount = 0;
            BotLines.ForEach(line =>
                {
                    var bot = line.profile.Bot;
                    var flag =  
                        !(bot.bnet == null || bot.bnet.Length < 3) ||
                        !(bot.d3_path == null || bot.d3_path.Length < 3) ||
                        !(bot.db_key == null || bot.db_key.Length < 3) ||
                        !(bot.db_path == null || bot.db_path.Length < 3) ||
                        !(bot.db_routine == null || bot.db_routine.Length < 3) ||
                        !(bot.pass == null || bot.pass.Length < 3);

                    if (flag) {
                        line.line_lb_setUnset.ForeColor = Color.Green;
                        line.line_lb_setUnset.Text = "READY";
                        line.line_btn_start.Enabled = true;
                        line.line_chb_enable.Enabled = true;
                        line.profile.Ready = true;
                        readyCount++;
                    } else {
                        line.line_lb_setUnset.ForeColor = Color.Red;
                        line.line_lb_setUnset.Text = "UNSET";
                        line.line_btn_start.Enabled = false;
                        line.line_chb_enable.Enabled = false;
                        line.line_chb_enable.Checked = false;
                    }

                });
            if (readyCount == 0)
                bt_startAll.Enabled = false;
            else {
                bt_startAll.Enabled = true;
                SavePlanFile();
            }
        }

        #endregion

        
        #region LOG

        private static ConcurrentQueue<string> LogQueue = new ConcurrentQueue<string>();

        string LastLogSMG = "";
        private List<string> Log(string text, bool ext = false)
        {
            if (LastLogSMG != text) LastLogSMG = text;
            else return new List<string>();

            var splitMsg = Regex.Split(text, @"(\|#\|)");

            var dt = DateTime.Now;

            #region Check file

            var path = Application.StartupPath;
            if (!Directory.Exists(path + "\\log")) Directory.CreateDirectory(path + "\\log");

            var filePath = string.Format("{0}\\log\\{1:00}-{2:00}-{3:0000}_", path, dt.Day, dt.Month, dt.Year);

            FileInfo logfile;
            var fileNum = 0;
            while (true)
            {
                logfile = new FileInfo(filePath + fileNum + ".txt");
                if (!File.Exists(logfile.DirectoryName + @"\" + logfile.Name)) break;
                if (logfile.Length < 1048576) break; // 1Mb
                fileNum++;
            }

            #endregion

            var appendText = logfile.AppendText();

            var MsgList = new List<string>();
            foreach (var msg in from ss in splitMsg
                                where ss != "|#|" && ss.Length > 0
                                select string.Format("{0:00}:{1:00}:{2:00}:{3:000} {4}",
                                                     dt.Hour, dt.Minute, dt.Second, dt.Millisecond, ss))
            {
                appendText.WriteLine(string.Format("{0:00}.{1:00}.{2:0000} {3}",
                                                   dt.Day, dt.Month, dt.Year, msg));

                MsgList.Add(string.Format("\r\n{0}", msg));
            }
            appendText.Close();
            appendText.Dispose();

            tb_logfile.Text = logfile.FullName;

            if (logbox.Text.Length >= 100000) logbox.Clear();
            if (ext) return MsgList;

            MsgList.ForEach(msg => logbox.AppendText(msg));

            return null;
        }

        #endregion
        

        #region UTILITES


        #endregion
     //*/   
    }

}
